/******************************************************
 * @file main_page.c
 * @author Destiny 
 * @brief 主页面构造程序
 * @version 0.1
 * @date 2024-07-18
 *****************************************************/
/* Includes ------------------------------------------------------------------*/
#include <pthread.h>
#include <stdlib.h>
#include <string.h>

/* Private Includes ----------------------------------------------------------*/
#include "config.h"
#include "render.h"
#include "file.h"
#include "page_manager.h"

/* Private typedef -----------------------------------------------------------*/

/* Private Define ------------------------------------------------------------*/
    /* 
     *   文件显示方式
     *   --------
     *   |  图  |
     *   |  标  |
     * ------------
     * |   名字   |
     * ------------
    */
#define APP_ICON_WIDTH      60                                 /*APP图标的宽*/
#define APP_ICON_HEIGHT     APP_ICON_WIDTH                     /*APP图标的高*/
#define APP_NAME_HEIGHT     30                                 /*APP名称的高*/
#define APP_NAME_WIDTH      (APP_ICON_WIDTH + APP_ICON_HEIGHT) /*APP名称的宽*/
#define APP_ALL_WIDTH        APP_NAME_WIDTH
#define APP_ALL_HEIGHT       APP_ALL_WIDTH
#define MIN_ICON_SPACING     15                               /*图标最小间距*/

/* Private variables ---------------------------------------------------------*/

/*APP图标*/
static T_Layout g_AppIconsLayout[] = {
    {0, 0, 0, 0, "/opt/icon/APP/game_icon.bmp"},
    {0, 0, 0, 0, "名称:游戏"},
    {0, 0, 0, 0, "/opt/icon/APP/settting.bmp"},
    {0, 0, 0, 0, "名称:设置"},
    {0, 0, 0, 0, "/opt/icon/APP/smart_home.bmp"},
    {0, 0, 0, 0, "名称:智能家居"},
    {0, 0, 0, 0, "/opt/icon/APP/video.bmp"},
    {0, 0, 0, 0, "名称:视频"},
    {0, 0, 0, 0, "/opt/icon/APP/reader.bmp"},
    {0, 0, 0, 0, "名称:阅读"},
    {0, 0, 0, 0, "/opt/icon/APP/File_Browser.bmp"},
    {0, 0, 0, 0, "名称:文件浏览"},
    {0, 0, 0, 0, "/opt/icon/APP/camera.bmp"},
    {0, 0, 0, 0, "名称:相机"},
    {0, 0, 0, 0, "/opt/icon/APP/picture.bmp"},
    {0, 0, 0, 0, "名称:相册"},
    {0, 0, 0, 0, "/opt/icon/APP/cnn.bmp"},
    {0, 0, 0, 0, "名称:神经网络"},
    {0, 0, 0, 0, NULL},
};

/*页面菜单栏布局*/
static T_PageLayout g_tMainPageIconsLayout = {
    .iMaxTotalBytes = 0,
    .atLayout = g_AppIconsLayout,
};

static int g_iAppNumPerCol, g_iAppNumPerRow;

/* Private Function Prototypes -----------------------------------------------*/

/**
 * @brief 计算页面图标位置
 * 
 * @param ptPageLayout 页面布局区域信息
*/
static void CalcMainPageLayout(PT_PageLayout ptPageLayout)
{
    int iXres, iYres, iBpp;
    int iTopLeftX, iTopLeftY;
    int iTopLeftXBak;
    int iBotRightX, iBotRightY;
    int iIconWidth, iIconHeight;
    int iNumPerCol, iNumPerRow;
    int iDeltaX, iDeltaY;
    int i, j, k = 0;
    PT_Layout atLayout;

    atLayout = ptPageLayout->atLayout;

    GetDispResolution(&iXres, &iYres, &iBpp);
    /*确定文件显示区域*/
    iTopLeftX = MIN_ICON_SPACING;
    iBotRightX = iXres - MIN_ICON_SPACING;
    iTopLeftY = MIN_ICON_SPACING;
    iBotRightY = iYres - MIN_ICON_SPACING;

    /*确定图标大小*/
    iIconWidth = APP_ALL_WIDTH;
    iIconHeight = APP_ALL_HEIGHT;

    /*计算区域内每行可以显示多少个文件图标*/
    iNumPerRow = (iBotRightX - iTopLeftX + 1) / iIconWidth;

    /*计算得到图标间隔大小，间隔不能小于MIN_ICON_SPACING*/
    while (1)
    {
        iDeltaX = (iBotRightX - iTopLeftX + 1) - iIconWidth * iNumPerRow;
        if ((iDeltaX / (iNumPerRow + 1)) < MIN_ICON_SPACING)
            iNumPerRow--;
        else
            break;
    }

    /*计算区域内每列可以显示多少个文件图标*/
    iNumPerCol = (iBotRightY - iTopLeftY + 1) / iIconHeight;
    while (1)
    {
        iDeltaY = (iBotRightY - iTopLeftY + 1) - iIconHeight * iNumPerCol;
        if ((iDeltaY / (iNumPerCol + 1)) < MIN_ICON_SPACING)
            iNumPerCol--;
        else
            break;
    }

    /*得到图标间的间隔*/
    iDeltaX = iDeltaX / (iNumPerRow + 1);
    iDeltaY = iDeltaY / (iNumPerCol + 1);

    g_iAppNumPerRow = iNumPerRow;
    g_iAppNumPerCol = iNumPerCol;
    
    /*计算每个图标的显示坐标*/
    iTopLeftX += iDeltaX;
    iTopLeftY += iDeltaY;
    iTopLeftXBak = iTopLeftX;

    for (i = 0; i < iNumPerCol; i++)
    {
        for (j = 0; j < iNumPerRow; j++)
        {
            atLayout[k].iTopLeftX = iTopLeftX + (APP_NAME_WIDTH - APP_ICON_WIDTH) / 2;  
            atLayout[k].iBotRightX = atLayout[k].iTopLeftX + APP_ICON_WIDTH - 1; 
            atLayout[k].iTopLeftY = iTopLeftY;
            atLayout[k].iBotRightY = iTopLeftY + APP_ICON_HEIGHT - 1;

            atLayout[k + 1].iTopLeftX = iTopLeftX; 
            atLayout[k + 1].iBotRightX = iTopLeftX + APP_NAME_WIDTH - 1;
            atLayout[k + 1].iTopLeftY = atLayout[k].iBotRightY + 1;
            atLayout[k + 1].iBotRightY = atLayout[k + 1].iTopLeftY + APP_NAME_HEIGHT - 1;

            iTopLeftX += APP_ALL_WIDTH + iDeltaX;
            k += 2;
            if(!atLayout[k].strIconName)     /*所有图标位置计算结束*/
            {
                goto
                    finish;   
            }
        }
        iTopLeftX = iTopLeftXBak;               /*计算完一行，开始新的一行*/
        iTopLeftY += APP_ALL_HEIGHT + iDeltaY;
    }
    finish:
        ptPageLayout->iBotRightX     = iBotRightX;
        ptPageLayout->iBotRightY     = iBotRightY;
        ptPageLayout->iTopLeftX      = iTopLeftX;
        ptPageLayout->iTopLeftY      = iTopLeftY;
        ptPageLayout->iBpp           = iBpp;
        ptPageLayout->iMaxTotalBytes = (atLayout[0].iBotRightX - atLayout[0].iTopLeftX + 1) * \
        (atLayout[0].iBotRightY - atLayout[0].iTopLeftY + 1) * iBpp / 8;
}

/**
 * @brief 获得输入事件(连续的两个索引表示同一个图标)
 * 
 * @param ptPageLayout main页面布局区域信息
 * @param ptInputEvent 输入事件信息
 * @return int 成功：被选择的图标索引;失败：-1
*/
static int MainPageGetInputEvent(PT_PageLayout ptPageLayout, PT_InputEvent ptInputEvent)
{
    return GenericGetInputEvent(ptPageLayout, ptInputEvent);
}

/**
 * @brief 将主页面图像数据写入缓冲区中
 * 
 * @param ptPageLayout main页面布局区域信息
 * @param ptVideoMem 显存结构体信息
*/
static void ShowMainPage(PT_PageLayout ptPageLayout, PT_VideoMem ptVideoMem)
{
    int iError;

    (void)iError;
    /*如果没有计算，那么算出图标位置*/
    if(!ptPageLayout->iMaxTotalBytes)
    {
        DBG_PRINTF(DLOG_LVL_INFO,DLOG_TAG,"CalcMainPageLayout!\n");
        CalcMainPageLayout(ptPageLayout);
    }
    /*将数据写入缓冲区*/
    iError = GeneratePage(ptPageLayout, ptVideoMem);
    //DBG_PRINTF(DLOG_LVL_ERROR,DLOG_TAG,"%s %d\n",__FILE__,__LINE__);
}

/**
 * @brief 图标被选择时，改变其图像数据
 * 
 * @param iAppIndex 图标索引
 * @param ptVideoMem 显存结构体信息
*/
static void SelectAppIcon(int iAppIndex,PT_VideoMem ptVideoMem)
{
    /*去掉最后一位,定位到图标*/
    iAppIndex = iAppIndex & ~1;

    InvertButton(&g_AppIconsLayout[iAppIndex],ptVideoMem);
    InvertButton(&g_AppIconsLayout[iAppIndex + 1],ptVideoMem);
}

/**
 * @brief 主页面运行逻辑
 * 
*/
static void MainPageRun(PT_PageParams ptParentPageParams)
{
    int iIndex;
    T_InputEvent tInputEvent;  //用以保存输入事件信息

    int bIconPressed = 0;
    int iIndexPressed = -1;

    /*当前页面参数*/
    T_PageParams tPageParams;
    tPageParams.iPageID = ID("main");

    PT_VideoMem ptDevVideoMem;  //显示设备显存
    PT_VideoMem ptPageVideoMem; //显示缓冲区

    ptPageVideoMem = GetVideoMem(tPageParams.iPageID, 1);
    if(ptPageVideoMem == NULL)
    {
        DBG_PRINTF(DLOG_LVL_ERROR,DLOG_TAG,"GetVideoMem for Page error!\r\n");
        return;
    }
    /*获取显示设备显存*/
    ptDevVideoMem = GetDevVideoMem();
    /*显示页面数据*/
    ShowMainPage(&g_tMainPageIconsLayout,ptPageVideoMem);
    /*缓冲区数据写入显示设备显存*/
    FlushVideoMemToDev(ptPageVideoMem);
    while (1)
    {
        /*读取输入事件,获取按钮索引，连续的两个索引表示同一个图标;如0和1都表示游戏图标*/
        iIndex = MainPageGetInputEvent(&g_tMainPageIconsLayout, &tInputEvent);

        /*无效输入*/
        if(iIndex == -1)   
        {
            goto mouse;
        }

        /*低位取0,得到对应图标索引*/
        iIndex = iIndex& ~1;

        if(tInputEvent.iPressure)   /*按压事件*/
        {
            if (!bIconPressed) /*之前没有图标被按下*/
            {
                bIconPressed = 1;
                iIndexPressed = iIndex;           /*记录按下的图标索引*/
                // tInputEventPrePress = tInputEvent;
                SelectAppIcon(iIndexPressed,ptPageVideoMem);
            }
        }
        else                     /*松开*/
        {
            /*如果没有图标被按下，不做处理*/
            if (!bIconPressed)
            {
                continue;
            }   
            bIconPressed = 0;
            if(iIndexPressed == iIndex)   /*松开和按下的是同一个按钮*/
            {
                switch (iIndex)
                {
                    case 0:
                    {
                        /*游戏*/
                        SelectAppIcon(iIndexPressed,ptPageVideoMem);
                        break;

                    }
                    case 2:
                    {
                        /*设置*/
                        SelectAppIcon(iIndexPressed,ptPageVideoMem);
                        break;
                    }
                    case 4:
                    {
                        /*智能家居*/
                        Page("smarthome")->Run(&tPageParams);
                        ShowMainPage(&g_tMainPageIconsLayout,ptPageVideoMem);
                        break;
                    }
                    case 6:
                    {
                        /*视频*/
                        SelectAppIcon(iIndexPressed,ptPageVideoMem);
                        break;
                    }
                    case 8:
                    {
                        /*阅读*/
                        Page("reader")->Run(&tPageParams);
                        ShowMainPage(&g_tMainPageIconsLayout,ptPageVideoMem);
                        break;
                    }
                    case 10:
                    {
                        /*文件浏览*/
                        Page("browse")->Run(&tPageParams);
                        ShowMainPage(&g_tMainPageIconsLayout,ptPageVideoMem);
                        break;

                    }
                    case 12:
                    {
                        /*相机*/
                        Page("camera")->Run(&tPageParams);
                        ShowMainPage(&g_tMainPageIconsLayout,ptPageVideoMem);
                        break;

                    }
                    case 14:
                    {
                        /*相册*/
                        Page("image")->Run(&tPageParams);
                        ShowMainPage(&g_tMainPageIconsLayout,ptPageVideoMem);
                        break;

                    }
                    case 16:
                    {
                        /*mnist*/
                        Page("mnist")->Run(&tPageParams);
                        ShowMainPage(&g_tMainPageIconsLayout,ptPageVideoMem);
                        break;

                    } 
                    default:
                        SelectAppIcon(iIndexPressed,ptPageVideoMem);
                        break;
                
                }

            }
            SelectAppIcon(iIndexPressed,ptPageVideoMem);
        }
    mouse:
        FlushVideoMemToDev(ptPageVideoMem);
        MergeMouseToDisp(&tInputEvent, ptDevVideoMem);
    }
    PutVideoMem(ptPageVideoMem);
}

/**
 * @brief main页面结构体
 * 
*/
static T_PageAction g_tMainPageAction = {
    .name = "main",
    .Run = MainPageRun,
    .GetInputEvent = MainPageGetInputEvent,
    //.Prepare       = BrowsePagePrepare;
};

/* Public Function Prototypes ------------------------------------------------*/

/**
 * @brief main页面注册函数
 * 
 * @return int 
*/
int MainPageInit(void)
{
    return RegisterPageAction(&g_tMainPageAction);
}
